package com.harmontronics.app.pedestal.bridge;

import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.text.TextUtils;
import android.webkit.JavascriptInterface;

import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;

import com.blankj.utilcode.util.DeviceUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ThreadUtils;
import com.blankj.utilcode.util.Utils;
import com.harmontronics.app.pedestal.R;
import com.harmontronics.app.pedestal.agent.WebActivity;
import com.harmontronics.app.pedestal.bridge.model.BaseBridge;
import com.harmontronics.app.pedestal.receiver.NotifyReceiver;

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
import org.json.JSONArray;
import org.json.JSONObject;

import java.nio.charset.Charset;

import wendu.dsbridge.CompletionHandler;

public class MqttBridge extends BaseBridge {

    private WebActivity activity;

    public MqttBridge(WebActivity activity) {
        this.activity = activity;
    }

    private MqttClient mqttClient;
    private MqttConnectOptions options;
    private String[] topics;

    @JavascriptInterface
    public void subscribe(Object argsJson, CompletionHandler<String> handler) {
        LogUtils.d("MQTT.subscribe");
        if (null == argsJson) {
            handler.complete(fail("参数不能为空", null));
            return;
        }

        try {
            JSONObject args = (JSONObject) argsJson;
            LogUtils.d("args: " + args.toString());
//            address
//            port
//            username
//            password
//            topics:[]
            if (!args.has("address") || TextUtils.isEmpty(args.getString("address"))) {
                throw new IllegalArgumentException("address must no be null");
            }

            if (!args.has("port")) {
                throw new IllegalArgumentException("port must no be null");
            }

            if (args.has("topics")) {
                JSONArray extension = args.getJSONArray("topics");
                if (extension.length() > 0) {
                    topics = new String[extension.length()];
                    for (int i = 0; i < extension.length(); i++) {
                        topics[i] = extension.getString(i);
                    }
                }
            }

            if (null == topics || topics.length == 0) {
                throw new IllegalArgumentException("topics must no be null");
            }

            if (null == mqttClient) {
                String uniqueId = DeviceUtils.getUniqueDeviceId(true);
                String serverUri = "tcp://" + args.getString("address") + ":" + args.getString("port");
                mqttClient = new MqttClient(serverUri, null != uniqueId && !TextUtils.isEmpty(uniqueId) ? uniqueId : "hancode_client",
                        new MemoryPersistence());
            }

            mqttClient.setCallback(new MqttCallbackExtended() {
                @Override
                public void connectComplete(boolean reconnect, String serverURI) {
                    LogUtils.d("connectComplete: " + serverURI);
                    handler.complete(success("connect success"));
                }

                @Override
                public void connectionLost(Throwable cause) {
                    LogUtils.d("connectionLost: " + cause.getMessage());
                    connect2Mqtt();
                }

                @Override
                public void messageArrived(String topic, MqttMessage message) throws Exception {
                    String msg = new String(message.getPayload(), Charset.forName("UTF-8"));
                    activity.onReceive(topic, msg);
                    try {
                        JSONObject msgObj = new JSONObject(msg);

                        if (msgObj.has("title") && !TextUtils.isEmpty(msgObj.getString("title")) &&
                                msgObj.has("content") && !TextUtils.isEmpty(msgObj.getString("content"))) {
                            sendNotification(msgObj.getString("title"), msgObj.getString("content"));
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

                @Override
                public void deliveryComplete(IMqttDeliveryToken token) {
                    LogUtils.d("deliveryComplete: " + token.toString());
                }
            });

            options = new MqttConnectOptions();
            // 在重新启动和重新连接时记住状态
            options.setCleanSession(true);
            options.setAutomaticReconnect(true);
            // 设置连接的用户名
            if (args.has("username")) {
                options.setUserName(args.getString("username"));
            }
            // 设置密码
            if (args.has("password")) {
                options.setPassword(args.getString("password").toCharArray());
            }

            // connnect
            connect2Mqtt();
        } catch (Exception e) {
            handler.complete(fail(e.getMessage(), e));
        }
    }

    @JavascriptInterface
    public void unsubscribe(Object args, CompletionHandler<String> handler) {
        LogUtils.d("MQTT.unsubscribe");
        try {
            if(mqttClient == null){
                handler.complete(success("MQTT.unsubscribe"));
                return;
            }
            if(topics != null && topics.length>0){
                mqttClient.unsubscribe(topics);
            }
            mqttClient.disconnect();
            handler.complete(success("MQTT.unsubscribe"));
        } catch (MqttException e) {
            handler.complete(fail(e.getMessage(), e));
        }
        //handler.complete(success("MQTT.unsubscribe"));
    }

    @JavascriptInterface
    public void onReceive(Object args, CompletionHandler<String> handler) {
        LogUtils.d("MQTT.onReceive");
        handler.complete("MQTT.onReceive");
    }

    private void connect2Mqtt() {
        ThreadUtils.getCachedPool().execute(new Runnable() {
            @Override
            public void run() {
                try {
                    // connect
                    mqttClient.connect(options);
                    // subscribe
                    mqttClient.subscribe(topics);//订阅主题，参数：主题、服务质量
                } catch (MqttException e) {
                    LogUtils.e(e);
                    if (e.getReasonCode() != 32100) {
                        connect2Mqtt();
                    }
                }
            }
        });
    }

    private void sendNotification(String title, String content) {
        String channelId = "hancode_channel_id";
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel(channelId, "hancode", NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription("hancode channel");
            NotificationManager notificationManager = Utils.getApp().getSystemService(NotificationManager.class);
            notificationManager.createNotificationChannel(channel);
        }

        Intent intent = new Intent(Utils.getApp(), NotifyReceiver.class);
        intent.putExtra("title", title);
        intent.putExtra("content", content);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(Utils.getApp(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);

        NotificationCompat.Builder builder = new NotificationCompat.Builder(Utils.getApp(), channelId)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle(title)
                .setContentText(content)
                .setAutoCancel(true)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_DEFAULT);

        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(Utils.getApp());

        notificationManager.notify(100, builder.build());
    }
}
